package com.weaver.qfengx.api.qihoo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.weaver.qfengx.*;
import okhttp3.Response;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.Map;

/**
 * 奇虎360 查杀云API对接工具类
 */
public class FileScanner {

    private static final LogUtils log = new LogUtils(FileScanner.class);

    private static FileScannerLogEntity commonLogEntity(FileScannerConfig config) {
        return new FileScannerLogEntity()
                .setAppid(config.getAppid())
                .setSecret(config.getSecret())
                .setDatetime(DateUtils.datetime());
    }

    /**
     * 同步扫描样本
     * @param config
     * @param file
     * @return
     */
    public static FileScannerResult sampleQuerySync(FileScannerConfig config, File file) {
        try {
            return sampleQuerySync(config, new FileInputStream(file), file.getName());
        } catch (Exception e) {
            log.writeLog("同步扫描样本异常 => ", e.getMessage());
            FileScannerLog.log(config, commonLogEntity(config).setMsg(e.getMessage()));
            throw new FileScannerException(e);
        }
    }

    /**
     * 同步扫描样本
     * @param config
     * @param inputStream
     * @return
     */
    public static FileScannerResult sampleQuerySync(FileScannerConfig config, InputStream inputStream) {
        return sampleQuerySync(config, inputStream, "");
    }

    /**
     * 同步扫描样本
     * @param config
     * @param inputStream
     * @return
     */
    public static FileScannerResult sampleQuerySync(FileScannerConfig config, InputStream inputStream, String filename) {
        try {
            checkConfig(config);
            long costTime = System.currentTimeMillis();
            FileScannerResult fileScannerResult = new FileScannerResult();
            String url = config.getHost() + ":" + config.getPort() + "/safe/api/" + config.getVerison() + "/samplequery";
            log.writeLog("奇虎360云查杀请求 (" + DateUtils.datetime() + ") => " + url);
            Map<String, String> headers = Maps.newHashMap();
            String ts = Long.toString(System.currentTimeMillis()).substring(0, 10);
            headers.put("X-360-Key", config.getAppid());
            headers.put("X-360-Nonce", ts.substring(2));
            headers.put("X-360-Timestamp", ts);
            headers.put("X-360-Signature", config.getSecret());
            byte[] filedata = IOUtils.toByteArray(inputStream);
            headers.put("Sample-Length", String.valueOf(filedata.length));
            headers.put("Connection", "Keep-Alive");
            Map<String, String> params = Maps.newHashMap();
            String key = CryptUtils.qihooMD5(filedata);
            params.put("key", key);
            Response response = RequestUtils.uploadFileAndParam(config.getOkHttpClient(), url, filedata, "content", "", headers, params);
            int code = response.code();
            String respStr = response.body().string();
            costTime = System.currentTimeMillis() - costTime;
            log.writeLog("完成奇虎360云查杀请求 (" + DateUtils.datetime() + ")");
            log.debug("查杀结果 => httpcode => " + code);
            log.debug("查杀结果 => respStr => " + respStr);
            fileScannerResult.setHttpCode(code)
                    .setResponse(respStr);
            FileScannerLogEntity logEntity = commonLogEntity(config)
                    .setCostTime(Long.toString(costTime))
                    .setHttpCode(String.valueOf(code))
                    .setFilename(filename)
                    .setFilesize(String.valueOf(filedata.length))
                    .setFilesizeZh(calcShowSize(filedata.length))
                    .setHttpResponse(respStr);
            if (response.isSuccessful()) { // 成功的时候解析json
                JSONObject resObj = JSON.parseObject(respStr);
                int ret = resObj.getInteger("ret");
                String msg = resObj.getString("msg");
                String data = resObj.getString("data");
                fileScannerResult.setRet(ret)
                        .setMsg(msg)
                        .setData(data);
                logEntity.setRet(String.valueOf(ret))
                        .setData(data)
                        .setMsg(msg);
                if (StringUtils.isNotEmpty(data) && fileScannerResult.getRet() == 0) {
                    JSONObject dataObj = JSON.parseObject(data);
                    JSONObject keyObj = dataObj.getJSONObject(key);
                    JSONArray resultArray = keyObj.getJSONArray("results");
                    JSONObject infoObj = resultArray.getJSONObject(0).getJSONObject("info");
                    fileScannerResult.setLevel(infoObj.getInteger("level"))
                            .setMalware(infoObj.getString("malware"))
                            .setVirus(infoObj.getInteger("level") > config.getVirusLevel())
                            .setExts(infoObj.getString("exts"));
                    logEntity.setScannerLevel(String.valueOf(fileScannerResult.getLevel()))
                            .setMalware(fileScannerResult.getMalware())
                            .setExts(fileScannerResult.getExts());
                }
            }
            FileScannerLog.log(config, logEntity
                    .setRequestHeader(JSON.toJSONString(headers))
                    .setRequestParam(JSON.toJSONString(params))
                    .setIsVirus(fileScannerResult.getLevel() > config.getVirusLevel() ? "0" : "1"));
            return fileScannerResult;
        } catch (Exception e) {
            log.writeLog("同步扫描样本异常 => ", e.getMessage());
            FileScannerLog.log(config, commonLogEntity(config).setMsg(e.getMessage()));
            throw new FileScannerException(e);
        }
    }

    /**
     * 检查配置类
     */
    public static void checkConfig(FileScannerConfig config) {
        log.debug("检查配置信息 => " + config);
        if (StringUtils.isEmpty(config.getHost())) {
            FileScannerLog.log(config, commonLogEntity(config).setMsg("FileScannerConfig 配置项缺少, host为空"));
            throw new FileScannerException("FileScannerConfig 配置项缺少, host为空");
        }
        if (StringUtils.isEmpty(config.getAppid())) {
            FileScannerLog.log(config, commonLogEntity(config).setMsg("FileScannerConfig 配置项缺少, appid为空"));
            throw new FileScannerException("FileScannerConfig 配置项缺少, appid为空");
        }
        if (StringUtils.isEmpty(config.getSecret())) {
            FileScannerLog.log(config, commonLogEntity(config).setMsg("FileScannerConfig 配置项缺少, secret为空"));
            throw new FileScannerException("FileScannerConfig 配置项缺少, secret为空");
        }
    }

    private static String calcShowSize(long size) {
        long K = 1024L;
        long M = 1024L * K;
        long G = 1024L * M;
        DecimalFormat df = new DecimalFormat("#.00");
        if (size < M) {
            return df.format(size / (K * 1.00D)) + "K";
        }
        if (size >= M && size < G) {
            return df.format(size / (M * 1.00D)) + "M";
        } else {
            return  df.format(size / (G * 1.00D)) + "G";
        }

    }

    public static void main(String[] args) {
        System.out.println(calcShowSize(64040448L));
    }

}
